home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Delphi Developer's Kit 1996
/
Delphi Developer's Kit 1996.iso
/
power
/
sprites
/
mchsprt.pas
< prev
next >
Wrap
Pascal/Delphi Source File
|
1995-12-22
|
26KB
|
843 lines
unit MChSprt;
{
Real Time Scaleable Sprites
Components
for
Borland Delphi
Copyright 1995 by
Marek A. Chmielowski
All rights reserved
These components and source code is released to the public domain under the condition
that it will not be used for commercial or "For Profit" ventures.
This code can be copied, used, and distributed freely providing that it is NOT
modified, no fee is charged, and it is not used in a package for which a charge
is made.
Please do NOT distribute components or source code if you altered them -
EVEN IF THIS IS ONLY BUG CORRECTION.
Let me know about the problem and the solution and I will implement it in the
next version (may be it will be the next version).
My e-mail:
76360,2775@compuserve.com
If you would like to use this component for shareware or commercial application
please contact me first by mail:
Marek Chmielowski
5/56 Kozia St.
Warsaw 00-070
Poland
or
Marek Chmielowski
10005 Broad St.
Bethesda, MD 20814
USA
}
interface
uses
SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
Forms, Dialogs, ExtCtrls, Buttons, StdCtrls, MChSpBg;
type
TMChSprite = class;
TSprPosFunc = function(AtTime: TDateTime):TPoint;
TSprOnBorder = procedure(AtTime: TDateTime);
TSprOnCollide = procedure(SprCollided: TMChSprite; AtTime: TDateTime);
TSprNoCollide = procedure(AtTime: TDateTime);
TMChSprite = class(TGraphicControl)
{ Public declarations or Published if $M+ }
private
{ Private declarations }
PSpriteMgr: TMChSpriteBgr;
FSprMgrSet: Boolean;
FSprBitmapOrig: TBitmap;
FSprTrColor: TColor;
FSprBitmap, FSprMask: TBitmap;
FSprBitSet: Boolean;
FSprSet: Boolean;
FSprOnCanvas: Boolean;
FSprInBuf: Boolean;
FSprToShow: Boolean;
FSprRepaint: Boolean;
FSprRunning: Boolean;
FSprPaused: Boolean;
FSprCruise: Boolean;
FSprFrom: TPoint;
FSprDest: TPoint;
FSprNextPos: TPoint;
FSprMoved: Boolean;
FSprCurrentRect: TRect;
FSprDirty: TDirtyReg;
FSprTimeToRun: TDateTime;
FSprHideAfter: Boolean;
FSprTimeRunning: TDateTime;
FSprTimeStarted: TDateTime;
FSprTimeUpdated: TDateTime;
FSprMoveVect: TPoint;
FSprPosFunc: TSprPosFunc;
FSprIndex: Cardinal;
FSprDragable: Boolean;
FSprScaleX: double;
FSprScaleY: double;
FSprRescale: Boolean;
FSprRefX: Integer;
FSprRefY: Integer;
FSprColliding: Boolean;
FSprCollisionMask: Boolean;
FSprRadiusX: Integer;
FSprRadiusY: Integer;
FSprGuessBgr: Boolean;
procedure SprSetBitmap(Bitmap: TBitmap; trColor: TColor);
procedure SprMakeMask(trColor: TColor);
procedure SprReplTrCl(trColor: TColor);
function SprMakeVect(From, Dest: TPoint):TPoint;
procedure SprGuessSpriteMgr;
procedure SprFreeNotOrig;
protected
{ Protected declarations }
procedure SprFree;
public
{ Public declarations }
FSprOnCollide: TSprOnCollide;
FSprOnBorder: TSprOnBorder;
FSprNoCollide: TSprNoCollide;
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure SprInit;
procedure SprSetMgr(BgrMgr: TMChSpriteBgr);
procedure SprUnSetMgr;
procedure SprSetBitmapOrig(Bitm: TBitmap);
procedure SprRenewBitmap;
procedure SprSetTrColor(trColor: TColor);
procedure SprShowAt(Dest: TPoint);
procedure SprShowPaused(Dest: TPoint);
procedure SprShowAtTime(JTime: TDateTime);
procedure SprShowOn;
procedure SprHide;
procedure SprHideTmp;
procedure SprStop;
function SprDesiredPos(AtTime: TDateTime):TPoint;
procedure SprGoTo(Dest: TPoint; TimeToRunSec: TDateTime);
procedure SprGo(From, Dest: TPoint; TimeToRunSec: TDateTime);
procedure SprRun(From,Dest: TPoint; TimeToRunSec: TDateTime);
procedure SprCruise(TimeToRunSec: TDateTime);
procedure SprMoveTo(Dest: TPoint);
function SprGetDirty: TDirtyReg;
function SprGetDirtyAndClear: TDirtyReg;
function SprHitTest(ScrP: TPoint): Boolean;
function SprHitAt(ScrP: TPoint): TPoint;
procedure SprSetScale(NewScale: double);
procedure SprSetScaleX(NewScaleX: double);
procedure SprSetScaleY(NewScaleY: double);
procedure SprSetRef(NewRef: TPoint);
procedure SprSetRefX(NewRefX: Integer);
procedure SprSetRefY(NewRefY: Integer);
function SprRefToLeftTop(ScrP: TPoint): TPoint;
function SprLeftTopToRef(ScrP: TPoint): TPoint;
function SprCheckCollision(TestSpr: TMChSprite; AtTime: TDateTime): Boolean;
function SprCheckBorders(AtTime: TDateTime): Boolean;
property SprPosFunc: TSprPosFunc read FSprPosFunc write FSprPosFunc;
property SprMask: TBitmap read FSprMask;
property SprBitmap: TBitmap read FSprBitmap;
property SprFrom: TPoint read FSprFrom;
property SprDest: TPoint read FSprDest;
property SprNextPos: TPoint read FSprNextPos;
property SprCurrentRect: TRect read FSprCurrentrect;
property SprInBuf: Boolean read FSprInBuf;
property SprOnCanvas: Boolean read FSprOnCanvas;
property SprRepaint: Boolean read FSprRepaint write FSprRepaint;
property SprIndex: Cardinal read FSprIndex write FSprIndex;
property SprOnCollide: TSprOnCollide read FSprOnCollide write FSprOnCollide;
property SprOnBorder: TSprOnBorder read FSprOnBorder write FSprOnBorder;
property SprNoCollide: TSprNoCollide read FSprNoCollide write FSprNoCollide;
property SprTimeUpdated: TDateTime read FSprTimeUpdated;
property SprTimeStarted: TDateTime read FSprTimeStarted;
property SprPaused: Boolean read FSprPaused write FSprPaused;
property SprCollisionMask: Boolean read FSprCollisionMask write FSprCollisionMask;
published
{ Published declarations - can be only class type or properties }
property Visible;
property Height default 1;
property Width default 1;
property Left;
property Top;
property SprSpriteBitmap: TBitmap read FSprBitmapOrig write SprSetBitmapOrig;
property SprTrColor: TColor read FSprTrColor write SprSetTrColor;
property SprHideAfter: Boolean read FSprHideAfter write FSprHideAfter default False;
property SprScaleX: double read FSprScaleX write SprSetScaleX;
property SprScaleY: double read FSprScaleY write SprSetScaleY;
property SprRefX: Integer read FSprRefX write SprSetRefX;
property SprRefY: Integer read FSprRefY write SprSetRefY;
property SprColliding: Boolean read FSprColliding write FSprColliding;
property SprRadiusX: Integer read FSprRadiusX write FSprRadiusX;
property SprRadiusY: Integer read FSprRadiusY write FSprRadiusY;
property SprGuessBgr: Boolean read FSprGuessBgr write FSprGuessBgr default False;
property SprDragable: Boolean read FSprDragable write FSprDragable default False;
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('Samples', [TMChSprite]);
end;
constructor TMChSprite.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
Visible:=False;
FSprBitmapOrig:=TBitmap.Create;
FSprCurrentRect:=Rect(Left,Top,Left+Width,Top+Height);
FSprTimeStarted:=time;
FSprNextPos:=Point(Left,Top);
FSprGuessBgr:=True;
FSprScaleX:=1.0;
FSprScaleY:=1.0;
end;
destructor TMChSprite.Destroy;
begin
SprFree;
inherited Destroy;
end;
procedure TMChSprite.SprFreeNotOrig;
begin
try
if FSprRunning then SprStop;
if FSprOnCanvas then SprHide;
FSprMask.Free;
FSprBitmap.Free;
finally
FSprBitSet:=False;
end;
end;
procedure TMChSprite.SprFree;
begin
SprFreeNotOrig;
FSprBitmapOrig.Free;
end;
procedure TMChSprite.SprInit;
begin
if not FSprMgrSet then SprGuessSpriteMgr;
if not FSprBitSet then SprRenewBitmap;
FSprSet:=True;
end;
procedure TMChSprite.SprSetMgr(BgrMgr: TMChSpriteBgr);
begin
PSpriteMgr:=BgrMgr;
FSprMgrSet:=True;
SprInit;
end;
procedure TMChSprite.SprUnSetMgr;
begin
if FSprRunning then SprStop;
SprHide;
SprHideTmp;
FSprDirty.Old:=FSprCurrentRect;
FSprDirty.New:=NulRect;
FSprOnCanvas:=False;
PSpriteMgr.BgrUpdateDirtyReg(SprGetDirty);
PSpriteMgr:=nil;
FSprIndex:=0;
FSprMgrSet:=False;
FSprSet:=False;
end;
procedure TMChSprite.SprGuessSpriteMgr;
var
i: Cardinal;
begin
if not FSprGuessBgr then Exit;
if Parent.ComponentCount>0 then
begin
for i:=0 to Parent.ComponentCount-1 do
begin
if Parent.Components[i] is TMChSpriteBgr then
begin
PSpriteMgr:=(Parent.Components[i] as TMChSpriteBgr);
FSprMgrSet:=True;
Break;
end;
end;
end;
end;
procedure TMChSprite.SprMakeMask(trColor: TColor);
var
ColTestBitm1,ColTestBitm2: TBitmap;
trColorInv: TColor;
begin
{ Used to find result of xor for colors on actual bitmap }
ColTestBitm1 := TBitmap.Create;
ColTestBitm1.width := 1;
ColTestBitm1.height:=1;
ColTestBitm2 := TBitmap.Create;
ColTestBitm2.width := 1;
ColTestBitm2.height:=1;
ColTestBitm1.Canvas.Pixels[0,0]:=trColor;
ColTestBitm2.Canvas.CopyMode:=cmSrcInvert;
ColTestBitm2.Canvas.Draw(0,0,ColTestBitm1);
trColorInv:=ColTestBitm2.Canvas.Pixels[0,0];
ColTestBitm1.free;
ColTestBitm2.free;
with SprMask.Canvas do
begin
{ Does NOT work well due to color mapping }
{Brush.Color:= ((trColor xor clWhite) and $00FFFFFF)
or (trColor and $0F000000);}
Brush.Color:= trColorInv;
BrushCopy( Rect(0,0,SprMask.Width,SprMask.Height),
FSprBitmap,
Rect(0,0,FSprBitmap.Width,FSprBitmap.Height),
trColor);
CopyMode:=cmSrcInvert; { src xor Dest) }
Draw(0,0,FSprBitmap);
end;
end;
procedure TMChSprite.SprReplTrCl(trColor: TColor);
begin
with FSprBitmap.Canvas do
begin
CopyMode:=cmSrcCopy;
Brush.Color:= clBlack;
BrushCopy( Rect(0,0,FSprBitmap.Width,FSprBitmap.Height),
FSprBitmap,
Rect(0,0,FSprBitmap.Width,FSprBitmap.Height),
trColor);
end;
end;
procedure TMChSprite.SprSetBitmap(Bitmap: TBitmap; trColor: TColor);
begin
if not FSprMgrSet then SprGuessSpriteMgr;
try
SprFreeNotOrig;
FSprTrColor:=trColor;
if not Bitmap.Empty then
begin
Width :=Bitmap.Width;
Height:=Bitmap.Height;
FSprBitmap := TBitmap.Create;
FSprMask := TBitmap.Create;
FSprBitmap.Width := Bitmap.Width;
FSprBitmap.Height := Bitmap.Height;
FSprMask.Width := Bitmap.Width;
FSprMask.Height := Bitmap.Height;
FSprBitmap.Canvas.Draw(0,0,Bitmap);
SprMakeMask(trColor);
SprReplTrCl(trColor);
FSprScaleX:=1.0;
FSprScaleY:=1.0;
FSprRefX:=Width div 2;
FSprRefY:=Height div 2;
FSprRadiusX:=Width div 2;
FSprRadiusY:=Height div 2;
FSprCurrentRect:=Rect(Left,Top,Left+Width,Top+Height);
FSprNextPos:=Point(Left+round(FSprRefX*FSprScaleX),Top+round(FSprRefY*FSprScaleY));
FSprBitSet:=True;
end;
except
SprFreeNotOrig;
end;
end;
procedure TMChSprite.SprSetTrColor(trColor: TColor);
begin
FSprTrColor:=trColor;
SprRenewBitmap;
end;
procedure TMChSprite.SprRenewBitmap;
begin
SprSetBitmap(FSprBitmapOrig,FSprTrColor);
end;
procedure TMChSprite.SprSetBitmapOrig(Bitm: TBitmap);
begin
Width :=Bitm.Width;
Height:=Bitm.Height;
FSprBitmapOrig.Width := Bitm.Width;
FSprBitmapOrig.Height := Bitm.Height;
FSprBitmapOrig.Canvas.Draw(0,0,Bitm);
SprRenewBitmap;
end;
procedure TMChSprite.SprHide;
begin
if FSprOnCanvas then
begin
FSprToShow:=False;
end;
end;
procedure TMChSprite.SprHideTmp;
begin
if not FSprMgrSet then SprGuessSpriteMgr;
if FSprInBuf then PSpriteMgr.BgrEraseBufRect(FSprCurrentRect);
FSprInBuf:=False;
end;
procedure TMChSprite.SprStop;
begin
FSprCruise:=False;
if FSprRunning then
begin
if FSprHideAfter then SprHide;
FSprRunning:=False;
end;
end;
function TMChSprite.SprGetDirty: TDirtyReg;
begin
SprGetDirty:=FSprDirty;
end;
function TMChSprite.SprGetDirtyAndClear: TDirtyReg;
begin
SprGetDirtyAndClear:=FSprDirty;
FSprDirty.Old:=NulRect;
FSprDirty.New:=NulRect;
end;
procedure TMChSprite.SprMoveTo(Dest: TPoint);
begin
FSprCruise:=False;
if FSprRunning then SprStop;
SprHide;
FSprNextPos:=Dest;
FSprTimeUpdated:=time;
FSprMoved:=True;
FSprTimeUpdated:=time;
end;
procedure TMChSprite.SprShowOn;
begin
if FSprMoved then SprShowAT(FSprNextPos)
else SprShowAT(SprLeftTopToRef(Point(Left,Top)));
end;
procedure TMChSprite.SprShowAt(Dest: TPoint);
begin
FSprCruise:=False;
if not FSprSet then SprInit;
if FSprRunning then SprStop;
FSprNextPos:=Dest;
FSprMoved:=True;
FSprToShow:=True;
FSprTimeUpdated:=time;
end;
procedure TMChSprite.SprShowPaused(Dest: TPoint);
begin
if not FSprSet then SprInit;
FSprNextPos:=Dest;
FSprMoved:=True;
FSprToShow:=True;
FSprTimeUpdated:=time;
end;
procedure TMChSprite.SprShowAtTime(JTime: TDateTime);
var
RcOld: TRect;
Stationary: Boolean;
NewPos: TPoint;
begin
if not FSprSet then SprInit;
if FSprToShow then
begin
RcOld:=FSprCurrentRect;
FSprTimeRunning:=JTime-FSprTimeStarted;
NewPos:= SprDesiredPos(JTime);
if FSprMoved then FSprMoved:=False;
if FSprOnCanvas and ((Left+SprRefX)=NewPos.x) and ((Top+SprRefY)=NewPos.y) and (not FSprRescale) then
Stationary:=True
else
begin
Stationary:=False;
Left:=SprRefToLeftTop(NewPos).x;
Top :=SprRefToLeftTop(NewPos).y;
Width :=round(SprBitmap.Width *FSprScaleX);
Height:=round(SprBitmap.Height*FSprScaleY);
FSprCurrentRect:=Rect(Left,Top,Left+Width,Top+Height);
FSprRescale:=False;
FSprNextPos:=NewPos;
FSprTimeUpdated:=JTime;
end;
{
PSpriteMgr.BgrScreenBuf.Canvas.CopyMode:=cmSrcAnd;
PSpriteMgr.BgrScreenBuf.Canvas.StretchDraw(FSprCurrentRect,FSprMask);
PSpriteMgr.BgrScreenBuf.Canvas.CopyMode:=cmSrcPaint;
PSpriteMgr.BgrScreenBuf.Canvas.StretchDraw(FSprCurrentRect,FSprBitmap);
}
PSpriteMgr.BgrScreenBufStretchMaskPaint(FSprCurrentRect,FSprMask,FSprBitmap);
FSprInBuf:=True;
if not Stationary then
begin
if FSprOnCanvas then FSprDirty.Old:=RcOld;
FSprDirty.New:=FSprCurrentRect;
end
else if SprRepaint then FSprDirty.New:=FSprCurrentRect;
FSprOnCanvas:=True;
if FSprHideAfter and (FSprTimeToRun>0) and ((JTime-FSprTimeStarted)>FSprTimeToRun) then
begin
FSprToShow:=False;
end;
end
else
begin
if FSprOnCanvas then
begin
FSprDirty.Old:=FSprCurrentRect;
FSprDirty.New:=NulRect;
FSprOnCanvas:=False;
end
else
begin
if FSprRunning and not FSprToShow then
begin
FSprTimeRunning:=JTime-FSprTimeStarted;
NewPos:= SprDesiredPos(JTime);
if FSprMoved then FSprMoved:=False;
Left:=SprRefToLeftTop(NewPos).x;
Top :=SprRefToLeftTop(NewPos).y;
Width :=round(SprBitmap.Width *FSprScaleX);
Height:=round(SprBitmap.Height*FSprScaleY);
FSprCurrentRect:=Rect(Left,Top,Left+Width,Top+Height);
FSprNextPos:=NewPos;
FSprTimeUpdated:=JTime;
end;
end;
end;
end;
procedure TMChSprite.SprGoTo(Dest: TPoint; TimeToRunSec: TDateTime);
begin
SprGo(SprLeftTopToRef(Point(Left,Top)),Dest,TimeToRunSec);
end;
procedure TMChSprite.SprGo(From, Dest: TPoint; TimeToRunSec: TDateTime);
begin
FSprCruise:=False;
if not FSprSet then SprInit;
if FSprRunning then SprStop;
FSprFrom:=From;
FSprDest:=Dest;
FSprTimeToRun:=TimeToRunSec/60.0/60.0/24.0;
FSprMoveVect:=SprMakeVect(FSprFrom,FSprDest);
FSprTimeStarted:=time;
FSprToShow:=True;
FSprRunning := True;
end;
procedure TMChSprite.SprCruise(TimeToRunSec: TDateTime);
begin
if not FSprSet then SprInit;
if FSprRunning then SprStop;
FSprTimeToRun:=TimeToRunSec/60.0/60.0/24.0;
FSprTimeStarted:=time;
FSprCruise:=True;
FSprToShow:=True;
FSprRunning := True;
end;
procedure TMChSprite.SprRun(From,Dest: TPoint; TimeToRunSec: TDateTime);
var
SNew : TBitmap;
RcOld,RcB: TRect;
PosNew:TPoint;
i:cardinal;
Done: Boolean;
WasOnCanvas: Boolean;
begin
if not FSprSet then SprInit;
if FSprRunning then SprStop;
WasOnCanvas:=FSprOnCanvas;
if FSprOnCanvas then SprHide;
if FSprOnCanvas or FSprInBuf then
begin
PSpriteMgr.BgrAppIdle(Self,Done);
PSpriteMgr.BgrUpdateDirtyRegToCanvas(DirtyReg(NulRect,FSprCurrentRect));
end;
PSpriteMgr.BgrPause:=True;
if (not FSprRunning) and (not FSprInBuf) and (not FSprOnCanvas) then
begin
SNew:=TBitmap.Create;
SNew.Width:=Width;
SNew.Height:=Height;
SNew.Canvas.CopyMode:=cmSrcCopy;
RcB:=Rect(0,0,Width,Height);
FSprFrom:=From;
FSprDest:=Dest;
FSprTimeToRun:=TimeToRunSec/60.0/60.0/24.0;
FSprMoveVect:=SprMakeVect(FSprFrom,FSprDest);
Left:=SprRefToLeftTop(From).x;
Top :=SprRefToLeftTop(From).y;
FSprCurrentRect:=Rect(Left,Top,Left+Width,Top+Height);
FSprNextPos:=From;
FSprMoved:=False;
FSprTimeStarted:=time;
FSprRunning:=True;
repeat
RcOld:=FSprCurrentRect;
FSprTimeRunning:=time-FSprTimeStarted;
PosNew:=SprDesiredPos(time);
if FSprMoved then FSprMoved:=False;
Left:=SprRefToLeftTop(PosNew).x;
Top :=SprRefToLeftTop(PosNew).y;
FSprCurrentRect:=Rect(Left,Top,Left+Width,Top+Height);
FSprNextPos:=PosNew;
{SNew.Canvas.CopyRect(RcB,PSpriteMgr.BgrScreenBuf.Canvas,FSprCurrentRect);}
PSpriteMgr.BgrScreenBufGetRect(RcB,SNew,FSprCurrentRect);
{
PSpriteMgr.BgrScreenBuf.Canvas.CopyMode := cmSrcAnd;
PSpriteMgr.BgrScreenBuf.Canvas.Draw(Point(Left,Top),FSprMask);
PSpriteMgr.BgrScreenBuf.Canvas.CopyMode := cmSrcPaint;
PSpriteMgr.BgrScreenBuf.Canvas.Draw(Point(Left,Top),FSprBitmap);
}
PSpriteMgr.BgrScreenBufDrawMaskPaint(Point(Left,Top),FSprMask,FSprBitmap);
FSprInBuf:=True;
{SprUpdateDirtyReg(RcOld,FSprCurrentRect);}
PSpriteMgr.BgrUpdateDirtyRegToCanvas(DirtyReg(RcOld,FSprCurrentRect));
{
PSpriteMgr.BgrScreenBuf.Canvas.CopyMode := cmSrcCopy;
PSpriteMgr.BgrScreenBuf.Canvas.Draw(Left,Top,SNew);
}
PSpriteMgr.BgrScreenBufDrawRect(Point(Left,Top),SNew);
FSprInBuf:=False;
until FSprTimeRunning>=FSprTimeToRun;
if SprHideAfter then PSpriteMgr.BgrUpdateDirtyReg(DirtyReg(NulRect,FSprCurrentRect))
{PSpriteMgr.SprUpdateDirtyReg(NulRect,FSprCurrentRect)}
else
begin
{
PSpriteMgr.BgrScreenBuf.Canvas.CopyMode := cmSrcAnd;
PSpriteMgr.BgrScreenBuf.Canvas.Draw(Left,Top,FSprMask);
PSpriteMgr.BgrScreenBuf.Canvas.CopyMode := cmSrcPaint;
PSpriteMgr.BgrScreenBuf.Canvas.Draw(Left,Top,FSprBitmap);
}
PSpriteMgr.BgrScreenBufDrawMaskPaint(Point(Left,Top),FSprMask,FSprBitmap);
FSprInBuf:=True;
FSprOnCanvas:=False;
FSprToShow:=True;
end;
FSprRunning:=False;
FSprNextPos:=PosNew;
PSpriteMgr.BgrPause:=False;
if WasOnCanvas and not SprHideAfter then
begin
SprShowAt(FSprNextPos);
end;
SNew.Free;
end;
end;
function TMChSprite.SprMakeVect(From, Dest: TPoint):TPoint;
begin
SprMakeVect:=Point( Dest.x-From.x, Dest.y-From.y );
end;
function TMChSprite.SprDesiredPos(AtTime: TDateTime):TPoint;
var
RTime: TDateTime;
begin
RTime:=AtTime-FSprTimeStarted;
if (not FSprRunning) then
begin
if not FSprMoved then SprDesiredPos:=SprLeftTopToRef(Point(Left,Top))
else
begin
SprDesiredPos:=SprNextPos;
end;
end
else
begin
if FSprCruise and (FSprTimeToRun>=0) and (RTime>FSprTimeToRun) then FSprCruise:=False;
if FSprCruise and Assigned(FSprPosFunc) and ((FSprTimeToRun<0) or (RTime<FSprTimeToRun)) then
begin
if FSprPaused then
begin
FSprPosFunc(AtTime);
SprDesiredPos:=SprNextPos;
end
else SprDesiredPos:=FSprPosFunc(AtTime);
end
else
begin
if FSprPaused then SprDesiredPos:=SprNextPos
else
begin
if RTime<=0 then
SprDesiredPos:=SprFrom
else
if (FSprTimeToRun>0) and (RTime<FSprTimeToRun) then
SprDesiredPos:=Point(
FSprFrom.x+trunc(RTime/FSprTimeToRun*FSprMoveVect.x),
FSprFrom.y+trunc(RTime/FSprTimeToRun*FSprMoveVect.y) )
else
SprDesiredPos:=SprDest;
end;
end;
end;
end;
function TMChSprite.SprHitTest(ScrP: TPoint): Boolean;
var
PTmp, PTmp2: TPoint;
begin
SprHitTest:=False;
if (FSprOnCanvas) and (InRect(ScrP, FSprCurrentRect) ) then
begin
if (SprScaleX<>0) and (SprScaleY<>0) then
begin
PTmp:=Point(ScrP.x-left-round(SprScaleX*SprRefX),ScrP.y-Top-round(SprScaleY*SprRefY));
PTmp2:=Point( round(PTmp.x/abs(SprScaleX))+SprRefX,round(PTmp.y/abs(SprScaleY))+SprRefY );
if (FSprMask.Canvas.Pixels[PTmp2.x,PTmp2.y]=clBlack) and
(FSprBitmap.Canvas.Pixels[PTmp2.x,PTmp2.y]<>clBlack) then
SprHitTest:=True;
end
else
begin
SprHitTest:=True;
end;
end;
end;
function TMChSprite.SprHitAt(ScrP: TPoint): TPoint;
var
PTmp, PTmp2: TPoint;
begin
if SprHitTest(ScrP) then
begin
PTmp:=Point(ScrP.x-left-round(SprScaleX*SprRefX),ScrP.y-Top-round(SprScaleY*SprRefY));
PTmp2:=Point( round(PTmp.x),round(PTmp.y) );
SprHitAt:=PTmp2;
end
else
SprHitAt:=NulPoint;
end;
procedure TMChSprite.SprSetScaleX(NewScaleX: double);
begin
FSprScaleX:=NewScaleX;
FSprRescale:=True;
FSprMoved:=True;
end;
procedure TMChSprite.SprSetScaleY(NewScaleY: double);
begin
FSprScaleY:=NewScaleY;
FSprRescale:=True;
FSprMoved:=True;
end;
procedure TMChSprite.SprSetScale(NewScale: double);
begin
FSprScaleX:=NewScale;
FSprScaleY:=NewScale;
FSprRescale:=True;
FSprMoved:=True;
end;
procedure TMChSprite.SprSetRefX(NewRefX: Integer);
begin
FSprRefX:=NewRefX;
FSprRescale:=True;
FSprMoved:=True;
end;
procedure TMChSprite.SprSetRefY(NewRefY: Integer);
begin
FSprRefY:=NewRefY;
FSprRescale:=True;
FSprMoved:=True;
end;
procedure TMChSprite.SprSetRef(NewRef: TPoint);
begin
FSprRefX:=NewRef.x;
FSprRefY:=NewRef.y;
FSprRescale:=True;
FSprMoved:=True;
end;
function TMChSprite.SprRefToLeftTop(ScrP: TPoint): TPoint;
begin
SprRefToLeftTop:=Point(ScrP.x-round(SprScaleX*SprRefX),ScrP.y-round(SprScaleY*SprRefY));
end;
function TMChSprite.SprLeftTopToRef(ScrP: TPoint): TPoint;
begin
SprLeftTopToRef:=Point(ScrP.x+round(SprScaleX*SprRefX),ScrP.y+round(SprScaleY*SprRefY));
end;
function TMChSprite.SprCheckCollision(TestSpr: TMChSprite; AtTime: TDateTime): Boolean;
var
TestPos, MyPos: TPoint;
Dist, MyRad, TestRad, alpha: double;
begin
SprCheckCollision:=False;
if FSprColliding and TestSpr.SprColliding then
begin
MyPos:=SprDesiredPos(AtTime);
TestPos:=TestSpr.SprDesiredPos(AtTime);
if (abs(MyPos.x-TestPos.x)<=(abs(SprScaleX*SprRadiusX)+abs(TestSpr.SprScaleX*TestSpr.SprRadiusX))) and
(abs(MyPos.y-TestPos.y)<=(abs(SprScaleY*SprRadiusY)+abs(TestSpr.SprScaleY*TestSpr.SprRadiusY))) then
begin
if (SprRadiusX<0) and (TestSpr.SprRadiusX<0) then SprCheckCollision:=True
else
begin
Dist:=sqrt( (1.0*(MyPos.x-TestPos.x))*(1.0*(MyPos.x-TestPos.x))+
(1.0*(MyPos.y-TestPos.y))*(1.0*(MyPos.y-TestPos.y))+1.0e-6 );
if abs(MyPos.x-TestPos.x)<1 then alpha:=0 else
alpha:=arctan( abs( (MyPos.y-TestPos.y)/(MyPos.x-TestPos.x) ) );
MyRad := sqrt( abs(SprScaleX*SprRadiusX)*sin(alpha)*abs(SprScaleX*SprRadiusX)*sin(alpha)+
abs(SprScaleY*SprRadiusY)*cos(alpha)*abs(SprScaleY*SprRadiusY)*cos(alpha) );
TestRad:= sqrt( abs(TestSpr.SprScaleX*TestSpr.SprRadiusX)*sin(alpha)*
abs(TestSpr.SprScaleX*TestSpr.SprRadiusX)*sin(alpha)+
abs(TestSpr.SprScaleY*TestSpr.SprRadiusY)*cos(alpha)*
abs(TestSpr.SprScaleY*TestSpr.SprRadiusY)*cos(alpha) );
if Dist<MyRad+TestRad then SprCheckCollision:=True;
end;
end;
end;
end;
function TMChSprite.SprCheckBorders(AtTime: TDateTime): Boolean;
var
TestPos, MyPos: TPoint;
Dist, MyRad, TestRad, alpha: double;
begin
SprCheckBorders:=False;
if FSprColliding then
begin
MyPos:=SprDesiredPos(AtTime);
if (MyPos.x-abs(SprScaleX*SprRadiusX)<=0) or
(MyPos.x+abs(SprScaleX*SprRadiusX)>=PSpriteMgr.ClientWidth) or
(MyPos.y-abs(SprScaleY*SprRadiusY)<=0) or
(MyPos.y+abs(SprScaleY*SprRadiusy)>=PSpriteMgr.ClientHeight) then
SprCheckBorders:=True;
end;
end;
end.